home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / archiver / uucosr10.arc / DECODE.C next >
C/C++ Source or Header  |  1991-06-02  |  9KB  |  440 lines

  1. /*
  2.  * The uudecoding module, stripped and modified from Dumas' UUD
  3.  * with GEM routines added. 
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <string.h>
  8.  
  9. #define MAXCHAR 256
  10. #define LINELEN 256
  11. #define FILELEN 128
  12. #define NORMLEN 60    /* allows for 80 encoded chars per line */
  13. #define MAXFILES 32
  14.  
  15. #define ifname    if_name
  16. #define ofname    of_name
  17.  
  18. #define SEQMAX 'z'
  19. #define SEQMIN 'a'
  20.  
  21. extern FILE *fopen();
  22. extern char *strcpy();
  23. extern char *strcat();
  24. char *getnword();
  25.  
  26. char seqch;
  27. int first, secnd, check, numl;
  28.  
  29. FILE *in, *out;
  30. char *pos;
  31. char *curarg;
  32. char ifname[FILELEN], ofname[FILELEN];
  33. int filenumber = 0;
  34. char blank, partc = '\0';
  35. int partn, lens;
  36. int onedone = 0;
  37. int chtbl[MAXCHAR], cdlen[NORMLEN + 3];
  38.  
  39. char lnbuf[128];    /* scratchpad for sprintf use */
  40.  
  41. int
  42. decode(ifname) char *ifname;
  43.     {
  44.     int mode;
  45.     register int i, j;
  46.     char dest[FILELEN], buf[LINELEN];
  47.  
  48.     if ((in = fopen(ifname, "r")) == NULL) 
  49.         {
  50.         form_alert(1,"[1][Unable to open|the input file][ABORT]");
  51.         return;
  52.         }
  53.     disp_process(ifname);
  54.     /*
  55.      * Set up the default translation table.
  56.      */
  57.     for (i = 0; i < ' '; i++) chtbl[i] = -1;
  58.     for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
  59.     for (i = ' ' + 64; i < MAXCHAR; i++) chtbl[i] = -1;
  60.     chtbl['`'] = chtbl[' '];    /* common mutation */
  61.     chtbl['~'] = chtbl['^'];    /* an other common mutation */
  62.     blank = ' ';
  63.     /*
  64.      * set up the line length table, to avoid computing lotsa * and / ...
  65.      */
  66.     cdlen[0] = 1;
  67.     for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4)
  68.         cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j));
  69.     /*
  70.      * search for header or translation table line.
  71.      */
  72.     for(;;)
  73.         {    /* master loop for multiple decodes in one file */
  74.         partn = 'a';
  75.         for(;;)
  76.             {
  77.             if (fgets(buf, sizeof buf, in) == NULL) /* end of file */
  78.                 {
  79.                 if(onedone) 
  80.                     {
  81.                     return;
  82.                     } 
  83.                 else 
  84.                     {
  85.                     form_alert(1,"[1][Out of data...|No \"begin\" line][ABORT]");
  86.                     return;
  87.                     }
  88.                 }
  89.             numl++;
  90.             if (strncmp(buf, "table", 5) == 0) 
  91.                 {
  92.                 gettable();
  93.                 continue;
  94.                 }
  95.             if (strncmp(buf, "begin ", 6) == 0) 
  96.                 break;
  97.             if (strncmp(buf, "BEGIN", 5) == 0) 
  98.                 continue;
  99.             }
  100.  
  101.         lens = strlen(buf);
  102.         if (lens) buf[--lens] = '\0';
  103.  
  104.         if ((pos = getnword(buf, 3))) 
  105.             {
  106.             strcpy(dest, pos);
  107.             } 
  108.         else
  109.             {
  110.             form_alert(1,"[1][No filename|in \"begin\" line][ABORT]");
  111.             return;
  112.             }
  113.  
  114. /* NEED CODE HERE FOR USER TO EDIT DESTINATION LINE */
  115.  
  116.         strcpy(ofname, dest);
  117.  
  118.         if((out = fopen(ofname, "wb")) == NULL) 
  119.             {
  120.             sprintf(lnbuf,"[1][Cannot open|output file|%s][ABORT]",
  121.                 ofname);
  122.             form_alert(1,lnbuf);
  123.             return;
  124.             }
  125.         seqch = SEQMAX;
  126.         check = 1;
  127.         first = 1;
  128.         secnd = 0;
  129.         uudecode();
  130.         fclose(out);
  131.         onedone = 1;
  132.         }    /* master loop for multiple decodes in one file */
  133.     }
  134.  
  135. /*
  136.  * Bring back a pointer to the start of the nth word.
  137.  */
  138. char *getnword(str, n) register char *str; register int n;
  139.     {
  140.     while((*str == '\t') || (*str == ' ')) str++;
  141.     if (! *str) return NULL;
  142.     while(--n) 
  143.         {
  144.         while ((*str != '\t') && (*str != ' ') && (*str)) str++;
  145.         if (! *str) return NULL;
  146.         while((*str == '\t') || (*str == ' ')) str++;
  147.         if (! *str) return NULL;
  148.         }
  149.     return str;
  150.     }
  151.  
  152. /*
  153.  * Install the table in memory for later use.
  154.  */
  155. gettable()
  156.     {
  157.     char buf[LINELEN];
  158.     register int c, n = 0;
  159.     register char *cpt;
  160.  
  161.     for (c = 0; c <= MAXCHAR; c++) chtbl[c] = -1;
  162.  
  163.     for(;;)
  164.         {
  165.         if (fgets(buf, sizeof buf, in) == NULL) 
  166.             {
  167.             form_alert(1,"[1][Unexpected EOF|in translation table][ABORT]");
  168.             return(-1);
  169.             }
  170.         numl++;
  171.         if (strncmp(buf, "begin", 5) == 0) 
  172.             {
  173.             form_alert(1,"[1][Incomplete|translation table][ABORT]");
  174.             return(-1);
  175.             }
  176.         cpt = buf + strlen(buf) - 1;
  177.         *cpt = ' ';
  178.         while (*(cpt) == ' ') 
  179.             {
  180.             *cpt = 0;
  181.             cpt--;
  182.             }
  183.         cpt = buf;
  184.         while (c = *cpt) 
  185.             {
  186.             if (chtbl[c] != -1) 
  187.                 {
  188.                 form_alert(1,"[1][Duplicate char|in translation table][ABORT]");
  189.                 return(-1);
  190.                 }
  191.             if (n == 0) blank = c;
  192.             chtbl[c] = n++;
  193.             if (n >= 64) return;
  194.             cpt++;
  195.             }
  196.         }
  197.     }
  198.  
  199. /*
  200.  * copy from in to out, decoding as you go along.
  201.  */
  202.  
  203. uudecode()
  204.     {
  205.     char buf[LINELEN], outl[LINELEN];
  206.     register char *bp, *ut;
  207.     register int *trtbl = chtbl;
  208.     register int n, c, rlen;
  209.     register unsigned int len;
  210.     for(;;) 
  211.         {
  212.         if (fgets(buf, sizeof buf, in) == NULL) 
  213.             {
  214.             form_alert(1,"[1][EOF before end|of encoded data][ABORT]");
  215.             fclose(out);
  216.             return(-1);
  217.             }
  218.         numl++;
  219. /*
  220.  * end of uuencoded file ?
  221.  */
  222.         if (strncmp(buf, "END", 3) == 0) 
  223.             {
  224.             for(;;)
  225.                 {
  226.                 /* look for another file */
  227.                 if (fgets(buf, sizeof buf, in) == NULL) 
  228.                     {
  229.                     fclose(out);
  230.                     return(-1);
  231.                     }
  232.                 if (strncmp(buf, "BEGIN", 5) == 0) break;
  233.                 }
  234.             if (fgets(buf, sizeof buf, in) == NULL) 
  235.                 {
  236.                 form_alert(1,"[1][EOF right after BEGIN][ABORT]");
  237.                 fclose(out);
  238.                 return(-1);
  239.                 }
  240.             }
  241.             
  242.         len = strlen(buf);
  243.         if (len) buf[--len] = '\0';
  244. /*
  245.  * Is it an unprotected empty line before the end line ?
  246.  */
  247.         if (len == 0) continue;
  248. /*
  249.  * Get the binary line length.
  250.  */
  251.         n = trtbl[*buf];
  252.         if (n >= 0) goto decod;
  253. /**********CHECK THE ABOVE; MOVE INTO MAIN LOOP?? ***********/
  254.  
  255. /*
  256.  * end of Dumas uuencoded file ?
  257.  */
  258.         if (strncmp(buf, "end", 3) == 0) return;
  259. /*
  260.  * end of current file ? : get next one.
  261.  */
  262.         if (strncmp(buf, "include", 7) == 0) 
  263.             {
  264.             if (getfile(buf) < 0)
  265.                 {
  266.                 sprintf(lnbuf,
  267.                     "[1][Can't get data:|%s][ABORT]",
  268.                     buf);
  269.                 return(-1);
  270.                 }
  271.             continue;
  272.             }
  273.         buf[20] = '\0'; /* limit length of line passed to GEM */
  274.         sprintf(lnbuf,"[1][Bad prefix|\"%s\"|in file:|%s][ABORT]",
  275.             buf, ifname);
  276.         form_alert(1,lnbuf);
  277.         return(-1);
  278. /*
  279.  * Sequence checking ?
  280.  */
  281. decod:        rlen = cdlen[n];
  282. /*
  283.  * Is it the empty line before the end line ?
  284.  */
  285.         if (n == 0) continue;
  286. /*
  287.  * Pad with blanks.
  288.  */
  289.         for (bp = &buf[c = len];
  290.             c < rlen; c++, bp++) *bp = blank;
  291. /*
  292.  * All this just to check for uuencodes that append a 'z' to each line....
  293.  */
  294.         if (secnd && check) 
  295.             {
  296.             secnd = 0;
  297.             if (buf[rlen] == SEQMAX) 
  298.                 check = 0;
  299.             }
  300.         else if (first && check) 
  301.             {
  302.             first = 0;
  303.             secnd = 1;
  304.             if (buf[rlen] != SEQMAX) 
  305.                 check = 0;
  306.             }
  307. /*
  308.  * There we check.
  309.  */
  310.         if (check) 
  311.             {
  312.             if (buf[rlen] != seqch) 
  313.                 {
  314.                 sprintf(lnbuf,"[1][Wrong sequence|line %d|in file:|%s][I know]",
  315.                     numl, ifname);
  316.                 form_alert(1,lnbuf);
  317.                 }
  318.             seqch--;
  319.             if (seqch < SEQMIN) seqch = SEQMAX;
  320.             }
  321. /*
  322.  * output a group of 3 bytes (4 input characters).
  323.  * the input chars are pointed to by p, they are to
  324.  * be output to file f.n is used to tell us not to
  325.  * output all of them at the end of the file.
  326.  */
  327.         ut = outl;
  328.         len = n;
  329.         bp = &buf[1];
  330.         while (n > 0) {
  331.             *(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
  332.             n--;
  333.             if (n) {
  334.                 *(ut++) = (trtbl[bp[1]] << 4) |
  335.                       (trtbl[bp[2]] >> 2);
  336.                 n--;
  337.             }
  338.             if (n) {
  339.                 *(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
  340.                 n--;
  341.             }
  342.             bp += 4;
  343.         }
  344.         if ((n = fwrite(outl, 1, len, out)) <= 0) 
  345.             {
  346.             form_alert(1,"[1][Error writing|decoded file][ABORT]");
  347.             return(-1);
  348.             }
  349.         }
  350.     }
  351.  
  352.  
  353. /*
  354.  * Find the next needed file, if if exists, otherwise try further
  355.  * on next file.
  356.  */
  357.  
  358. getfile(buf) register char *buf;
  359.     {
  360.     if ((pos = getnword(buf, 2)) == NULL) 
  361.         {
  362.         form_alert(1,"[1][No include-file|name specified][ABORT]");
  363.         return(-1);
  364.         } 
  365.  
  366.     /* Some encoders are specifying filenames illegal for GEMdos */
  367.     /* The following transforms filename.arc.uab into filename.uab */
  368.     {
  369.     char *p, *q;
  370.     p = strchr(pos,'.');
  371.     q = strrchr(pos,'.');
  372.     if ((p != q) && p && q)
  373.         strcpy(p,q);
  374.     }
  375.  
  376.     strcpy(ifname, pos);
  377.  
  378.     if (exists(ifname))
  379.         {
  380.         if (freopen(ifname, "r", in) == in) 
  381.             {
  382.             disp_process(ifname);
  383.             numl = 0;
  384.             } 
  385.         else 
  386.             {
  387.             sprintf(lnbuf,"[1][freopen failure|while attempting|%s][ABORT]",
  388.                 ifname);
  389.             form_alert(1,lnbuf);
  390.             return(-1);
  391.             }
  392.         }
  393.  
  394.     for(;;)
  395.         {
  396.         /* read lines, looking for table or begin */
  397.         if (fgets(buf, LINELEN, in) == NULL) 
  398.             {
  399.             sprin